/*
 * Copyright (c) 2009, Magnus Robertsson. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package se.jayway.javafxbinder.model;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;

/**
 * Represent a Java type with a number of properties that can be connected to
 * a JavaFx equivalent adapter type.
 *
 * @author Magnus Robertsson
 */
public class TypeInfo {
	private final Class<?> type;

	public TypeInfo(Class<?> type) {
		this.type = type;
	}

	public String getName() {
		return type.getName();
	}

	public String getSimpleName() {
		return type.getSimpleName();
	}
	
	/**
	 * Returns the names of all types that are used as properties. Standard
	 * types are filtered out, i.e. java.lang classes won't be returned.
	 * 
	 * @return An array with types for all properties.
	 */
	public TypeInfo[] getPropertyTypes() {
    	List<TypeInfo> typeInfos = new ArrayList<TypeInfo>();
    	try {
			BeanInfo beanInfo = Introspector.getBeanInfo(type);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
				TypeInfo propertyType = new TypeInfo(propertyDescriptor.getPropertyType());
				if (!propertyType.isStandard()) {
					typeInfos.add(propertyType);
				}
			}
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}
		return typeInfos.toArray(new TypeInfo[typeInfos.size()]);
	}

	/**
	 * Returns true if this class is part of the standard Java libary.
	 * 
	 * @return True for standard classes such as java.lang.Integer or boolean.
	 */
    private boolean isStandard() {
		return getPackageName().equals("java.lang") || type.isPrimitive();
	}

	public String getPackageName() {
		int index = getName().lastIndexOf(".");
		if (index == -1) {
			return getName();
		} else {
			return getName().substring(0, index);
		}
	}

	public PropertyInfo[] getProperties() {
    	List<PropertyInfo> propertyInfos = new ArrayList<PropertyInfo>();
    	try {
			BeanInfo beanInfo = Introspector.getBeanInfo(type);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
				if (!propertyDescriptor.getName().equals("class")) {
					propertyInfos.add(new PropertyInfo(propertyDescriptor));
				}
			}
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}
		return propertyInfos.toArray(new PropertyInfo[propertyInfos.size()]);
    }
}
